﻿using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace PowerGui.AddOn.Interfaces
{
    /// <summary>
    /// The interface for interacting with the PowerGUI debugger.
    /// </summary>
    public interface IDebugger
    {
        /// <summary>
        /// Executes the current script editor.
        /// </summary>
        void Execute();
        /// <summary>
        /// Executes the current script editor without debugging.
        /// </summary>
        void ExecuteNoDebug();
        /// <summary>
        /// Executes the specified PowerShell script file.
        /// </summary>
        /// <param name="fileName">The file name of the PowerShell script to execute.</param>
        void Execute(string fileName);
        /// <summary>
        /// Executes the specified text.
        /// </summary>
        /// <param name="script">The text to execute.</param>
        void ExecuteText(string script);
        /// <summary>
        /// Breaks the PowerGUI debugger.
        /// </summary>
        void Break();
        /// <summary>
        /// Stops the PowerGUI debugger.
        /// </summary>
        void Stop();
        /// <summary>
        /// Sets the specified variable to the specified value for
        /// the current Runspace.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="obj"></param>
        void SetVariable(string name, object obj);
        /// <summary>
        /// Gets or sets the currently active script editor the debugger is targeting.
        /// </summary>
        IScriptEditor CurrentEditor { get; set; }
        /// <summary>
        /// Returns the Runspace the debugger is running in.
        /// </summary>
        Runspace Runspace { get; }
        /// <summary>
        /// Returns the internal debugger.
        /// </summary>
        object InternalDebugger { get; }
        /// <summary>
        /// Invoked when a script is started.
        /// </summary>
        event EventHandler ScriptStarted;
        /// <summary>
        /// Invoked when a script is stopped.
        /// </summary>
        event EventHandler ScriptCompleted;
        /// <summary>
        /// Invoked when a script fails with errors.
        /// </summary>
        event EventHandler<EventArgs<IPipelineStateInfo>> ScriptFailed;
        /// <summary>
        /// Invoked when a script becomes suspended. For example, when a breakpoint is hit.
        /// </summary>
        event EventHandler<EventArgs<IScriptPosition>> ScriptSuspended;
        /// <summary>
        /// Invoked when a script is resumed after being suspended.
        /// </summary>
        event EventHandler ScriptResumed;
        /// <summary>
        /// Invoked when a script editor becomes active.
        /// </summary>
        event EventHandler<EventArgs<IScriptEditor, bool>> ActivateEditor;
        /// <summary>
        /// Invoked when the debugger is writing to the pipeline.
        /// </summary>
        event EventHandler<EventArgs<string>> Write;
        /// <summary>
        /// Invoked when the debugger is writing a warning to the pipeline.
        /// </summary>
        event EventHandler<EventArgs<string>> WriteWarning;
        /// <summary>
        /// Invoked when the debugger is writing an error to the pipeline.
        /// </summary>
        event EventHandler<EventArgs<string>> WriteError;
        /// <summary>
        /// Invoked when the debugger is writing a verbose message to the pipeline.
        /// </summary>
        event EventHandler<EventArgs<string>> WriteVerbose;
        /// <summary>
        /// Invoked when the debugger is writing a debug message to the pipeline.
        /// </summary>
        event EventHandler<EventArgs<string>> WriteDebug;
        /// <summary>
        /// Invoked when the debugger is writing progress.
        /// </summary>
        event EventHandler<EventArgs<ProgressRecord>> WriteProgress;

         

    }

    public class EventArgs<T> : EventArgs
    {
        public EventArgs(T value)
        {
            _mValue = value;
        }

        private readonly T _mValue;

        public T Value
        {
            get { return _mValue; }
        }
    }

    public class EventArgs<T, T1> : EventArgs
    {
        public EventArgs(T value, T1 value2)
        {
            _mValue = value;
            Value2 = value2;
        }

        private readonly T _mValue;

        public T Value
        {
            get { return _mValue; }
        }

        public T1 Value2
        {
            get;
            private set;
        }
    }
}
